home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / upc12bs1.zip / UUCICO / dcpxfer.c < prev    next >
C/C++ Source or Header  |  1993-10-02  |  52KB  |  1,420 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    d c p x f e r . c                                               */
  3. /*                                                                    */
  4. /*    Procotol independent transfer level for UUCICO                  */
  5. /*                                                                    */
  6. /*    Stuart Lynne May/87                                             */
  7. /*                                                                    */
  8. /*    Copyright (c) Richard H. Lamb 1985, 1986, 1987                  */
  9. /*    Changes Copyright (c) Stuart Lynne 1987                         */
  10. /*    Changes Copyright (c) Jordan Brown 1990, 1991                   */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*       Changes Copyright (c) 1989-1993 by Kendra Electronic         */
  15. /*       Wonderworks.                                                 */
  16. /*                                                                    */
  17. /*       All rights reserved except those explicitly granted by       */
  18. /*       the UUPC/extended license agreement.                         */
  19. /*--------------------------------------------------------------------*/
  20.  
  21. /*
  22.  *       $Id: dcpxfer.c 1.24 1993/10/02 22:56:59 ahd Exp $
  23.  *
  24.  *       $Log: dcpxfer.c $
  25.  * Revision 1.24  1993/10/02  22:56:59  ahd
  26.  * Suppress compile warning
  27.  *
  28.  * Revision 1.23  1993/09/23  03:26:51  ahd
  29.  * Don't allow remote sites to send call files!
  30.  *
  31.  * Revision 1.22  1993/09/20  04:46:34  ahd
  32.  * OS/2 2.x support (BC++ 1.0 support)
  33.  * TCP/IP support from Dave Watt
  34.  * 't' protocol support
  35.  *
  36.  * Revision 1.21  1993/09/02  12:08:17  ahd
  37.  * HPFS Support
  38.  *
  39.  * Revision 1.20  1993/08/08  17:39:09  ahd
  40.  * Denormalize path for opening on selected networks
  41.  *
  42.  * Revision 1.19  1993/07/22  23:22:27  ahd
  43.  * First pass at changes for Robert Denny's Windows 3.1 support
  44.  *
  45.  *
  46.  * Revision 1.17  1993/05/30  00:04:53  ahd
  47.  * Multiple communications drivers support
  48.  *
  49.  * Revision 1.16  1993/05/09  03:41:47  ahd
  50.  * Don't expand path of files destined for UUCP spool
  51.  * Correct syslog processing to not close when not multitasking
  52.  *
  53.  * Revision 1.15  1993/05/06  03:41:48  ahd
  54.  * Reformat syslog output into readable format
  55.  * parse userids off incoming commands again
  56.  *
  57.  * Revision 1.14  1993/04/11  00:34:11  ahd
  58.  * Global edits for year, TEXT, etc.
  59.  *
  60.  * Revision 1.13  1993/04/10  21:25:16  dmwatt
  61.  * Add Windows/NT support
  62.  *
  63.  * Revision 1.12  1993/04/05  04:35:40  ahd
  64.  * Allow unique send/receive packet sizes
  65.  *
  66.  * Revision 1.11  1993/01/23  19:08:09  ahd
  67.  * Don't enable unbuffered I/O twice if not multitask mode
  68.  *
  69.  * Revision 1.10  1992/12/01  04:37:03  ahd
  70.  * Suppress routine names transfered from debug level 0 and 1
  71.  *
  72.  * Revision 1.9  1992/11/29  22:09:10  ahd
  73.  * Change size_t to int to suppress warning message
  74.  *
  75.  * Revision 1.8  1992/11/28  19:51:16  ahd
  76.  * If in multitask mode, only open syslog on demand basis
  77.  *
  78.  * Revision 1.7  1992/11/22  21:20:45  ahd
  79.  * Make databuf char rather than unsigned char
  80.  *
  81.  * Revision 1.6  1992/11/20  12:39:10  ahd
  82.  * Add instead of substracting on the receive buffer!
  83.  *
  84.  * Revision 1.5  1992/11/19  03:01:31  ahd
  85.  * drop rcsid
  86.  *
  87.  * Revision 1.4  1992/11/19  02:36:12  ahd
  88.  * Insure log file is flushed
  89.  *
  90.  * Revision 1.3  1992/11/17  13:44:24  ahd
  91.  * Drop command[BUFSIZ], using databuf instead.
  92.  *
  93.  * Revision 1.2  1992/11/15  20:09:50  ahd
  94.  * Use unbuffered files to eliminate extra data copy
  95.  * Clean up modem file support for different protocols
  96.  *
  97.  */
  98.  
  99.  /*
  100.    Additional maintenance Notes:
  101.  
  102.    01Nov87 - that strncpy should be a memcpy! - Jal
  103.    22Jul90 - Add check for existence of the file before writing
  104.              it.                                                  ahd
  105.    09Apr91 - Add numerous changes from H.A.E.Broomhall and Cliff
  106.              Stanford for bidirectional support                   ahd
  107.    05Jul91 - Merged various changes from Jordan Brown's (HJB)
  108.              version of UUPC/extended to clean up transmission
  109.              of commands, etc.                                    ahd
  110.    09Jul91 - Rewrite to use unique routines for all four kinds of
  111.              transfers to allow for testing and security          ahd
  112.  */
  113.  
  114.  
  115. /*--------------------------------------------------------------------*/
  116. /*                        System include files                        */
  117. /*--------------------------------------------------------------------*/
  118.  
  119. #include <ctype.h>
  120. #include <fcntl.h>
  121. #include <direct.h>
  122. #include <io.h>
  123. #include <stdio.h>
  124. #include <stdlib.h>
  125. #include <string.h>
  126. #include <time.h>
  127. #include <sys/types.h>
  128. #include <sys/stat.h>
  129. #include <sys/timeb.h>
  130.  
  131. /*--------------------------------------------------------------------*/
  132. /*                    UUPC/extended include files                     */
  133. /*--------------------------------------------------------------------*/
  134.  
  135. #include "lib.h"
  136. #include "dcp.h"
  137. #include "dcpsys.h"
  138. #include "dcpxfer.h"
  139. #include "expath.h"
  140. #include "hlib.h"
  141. #include "hostable.h"
  142. #include "import.h"
  143. #include "security.h"
  144. #include "modem.h"
  145.  
  146. /*--------------------------------------------------------------------*/
  147. /*                          Global variables                          */
  148. /*--------------------------------------------------------------------*/
  149.  
  150. static char *databuf = NULL;
  151. static unsigned int xferBufSize = 0;
  152.  
  153. static char fName[FILENAME_MAX], tName[FILENAME_MAX], dName[FILENAME_MAX];
  154. static char *lName;           // Name to report in syslog
  155. static char type, cmdopts[16];
  156.  
  157. static long bytes;
  158. static struct timeb startTime;
  159.  
  160. static boolean spool = FALSE; /* Received file is into spool dir     */
  161. static char spolName[FILENAME_MAX];
  162.                               /* Final host name of file to be
  163.                                  received into spool directory       */
  164. static char tempName[FILENAME_MAX];
  165.                               /* Temp name used to create received
  166.                                  file                                */
  167. static char userid[20];
  168.  
  169. currentfile();
  170.  
  171. /*--------------------------------------------------------------------*/
  172. /*                    Internal function prototypes                    */
  173. /*--------------------------------------------------------------------*/
  174.  
  175. static boolean pktgetstr( char *s);
  176. static boolean pktsendstr( char *s );
  177. static void buf_init( void );
  178.  
  179. static int  bufill(char  *buffer);
  180. static int  bufwrite(char  *buffer,int  len);
  181.  
  182. /*************** SEND PROTOCOL ***************************/
  183.  
  184. /*--------------------------------------------------------------------*/
  185. /*    s d a t a                                                       */
  186. /*                                                                    */
  187. /*    Send File Data                                                  */
  188. /*--------------------------------------------------------------------*/
  189.  
  190. XFER_STATE sdata( void )
  191. {
  192.    int S_size;
  193.    int used = 0;
  194.  
  195.    S_size = bufill((char *) databuf);
  196.  
  197.    if (S_size == 0)                 /* Get data from file         */
  198.       return XFER_SENDEOF;          /* if EOF set state to that   */
  199.    else if (S_size == -1)           /* If error ...               */
  200.       return XFER_ABORT;            /* Toss file                  */
  201.  
  202.    do {
  203.       short xmit = min( (size_t) S_size - used , s_pktsize );
  204.  
  205.       if ((*sendpkt)((char *) databuf + used, xmit) != DCP_OK)
  206.                                     /* Send data fail?            */
  207.       {
  208.          fclose( xfer_stream );
  209.          xfer_stream = NULL;
  210.          return XFER_LOST;    /* Trouble!                         */
  211.       }
  212.       else
  213.          used += xmit;
  214.  
  215.    } while( S_size > used );
  216.  
  217.    return XFER_SENDDATA;   /* Remain in send state                */
  218.  
  219. } /*sdata*/
  220.  
  221.  
  222. /*--------------------------------------------------------------------*/
  223. /*    b u f i l l                                                     */
  224. /*                                                                    */
  225. /*    Get a bufferful of data from the file that's being sent.        */
  226. /*    (Should perform input buffering here, perhaps 4K at a time.)    */
  227. /*--------------------------------------------------------------------*/
  228.  
  229. static int bufill(char *buffer)
  230. {
  231.    size_t count = fread(buffer,
  232.                         sizeof *buffer,
  233.                         xferBufSize,
  234.                         xfer_stream);
  235.  
  236.    bytes += count;
  237.    if ((count < xferBufSize) && ferror(xfer_stream))
  238.    {
  239.       printerr("bufill");
  240.       clearerr(xfer_stream);
  241.       return -1;
  242.    }
  243.    return count;
  244.  
  245. } /*bufill*/
  246.  
  247. /*--------------------------------------------------------------------*/
  248. /*    b u f w r i t e                                                 */
  249. /*                                                                    */
  250. /*    Write a bufferful of data to the file that's being received.    */
  251. /*--------------------------------------------------------------------*/
  252.  
  253. static int bufwrite(char *buffer, int len)
  254. {
  255.    int count = fwrite(buffer, sizeof *buffer, len, xfer_stream);
  256.  
  257.    bytes += count;
  258.    if (count < len)
  259.    {
  260.       printerr("bufwrite");
  261.       printmsg(0, "bufwrite: Tried to write %d bytes, actually wrote %d",
  262.         len, count);
  263.       clearerr(xfer_stream);
  264.    }
  265.  
  266.    return count;
  267.  
  268. } /*bufwrite*/
  269.  
  270. /*--------------------------------------------------------------------*/
  271. /*    s b r e a k                                                     */
  272. /*                                                                    */
  273. /*    Switch from master to slave mode                                */
  274. /*                                                                    */
  275. /*    Sequence:                                                       */
  276. /*                                                                    */
  277. /*       We send "H" to other host to ask if we should hang up        */
  278. /*       If it responds "HN", it has work for us, we become           */
  279. /*          the slave.                                                */
  280. /*       If it responds "HY", it has no work for us, we               */
  281. /*          response "HY" (we have no work either), and               */
  282. /*          terminate protocol and hangup                             */
  283. /*                                                                    */
  284. /*    Note that if more work is queued on the local system while      */
  285. /*    we are in slave mode, schkdir() causes us to become the         */
  286. /*    master again; we just decline here to avoid trying the queue    */
  287. /*    again without intervening work from the other side.             */
  288. /*--------------------------------------------------------------------*/
  289.  
  290. XFER_STATE sbreak( void )
  291. {
  292.    if (!pktsendstr("H"))      /* Tell slave it can become the master */
  293.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  294.  
  295.    if (!pktgetstr((char *)databuf)) /* Get their response            */
  296.       return XFER_LOST;       /* Xmit fail?  If so, quit transmitting*/
  297.  
  298.    if ((*databuf != 'H') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  299.    {
  300.       printmsg(0,"Invalid response from remote: %s",databuf);
  301.       return XFER_ABORT;
  302.    }
  303.  
  304.    if (databuf[1] == 'N')     /* "HN" (have work) message from host? */
  305.    {                          /* Yes --> Enter Receive mode          */
  306.       printmsg( 2, "sbreak: Switch into slave mode" );
  307.       return XFER_SLAVE;
  308.    }
  309.    else {                     /* No --> Remote host is done as well  */
  310.       pktsendstr("HY");       /* Tell the host we are done as well   */
  311.       hostp->hstatus = called;/* Update host status flags            */
  312.       return XFER_ENDP;       /* Terminate the protocol              */
  313.    } /* else */
  314.  
  315. } /*sbreak*/
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*    s e o f                                                         */
  319. /*                                                                    */
  320. /*    Send End-Of-File                                                */
  321. /*--------------------------------------------------------------------*/
  322.  
  323. XFER_STATE seof( const boolean purge_file )
  324. {
  325.  
  326.    struct tm  *tmx;
  327.    long ticks;
  328.    struct timeb now;
  329.  
  330. /*--------------------------------------------------------------------*/
  331. /*    Send end-of-file indication, and perhaps receive a              */
  332. /*    lower-layer ACK/NAK                                             */
  333. /*--------------------------------------------------------------------*/
  334.  
  335.    switch ((*eofpkt)())
  336.    {
  337.       case DCP_RETRY:            /* retry */
  338.          printmsg(0, "Remote system asks that the file be resent");
  339.          fseek(xfer_stream, 0L, SEEK_SET);
  340.          bytes = 0;
  341.          (*filepkt)();           /* warmstart file-transfer protocol */
  342.          return XFER_SENDDATA;   /* stay in data phase */
  343.  
  344.       case DCP_FAILED:
  345.          fclose(xfer_stream);
  346.          xfer_stream = NULL;
  347.          return XFER_ABORT;      /* cannot send file */
  348.  
  349.       case DCP_OK:
  350.          fclose(xfer_stream);
  351.          xfer_stream = NULL;
  352.          break;                  /* sent, proceed */
  353.  
  354.       default:
  355.          fclose(xfer_stream);
  356.          xfer_stream = NULL;
  357.          return XFER_LOST;
  358.    }
  359.  
  360.    if (!pktgetstr((char *)databuf)) /* Receive CY or CN              */
  361.       return XFER_LOST;       /* Bomb the connection if no packet    */
  362.  
  363.    if ((*databuf != 'C') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  364.    {
  365.       printmsg(0,"Invalid response from remote: %s",
  366.                   ( char *) databuf);
  367.       return XFER_ABORT;
  368.    }
  369.  
  370.    if (!equaln((char *) databuf, "CY", 2))
  371.       printmsg(0,"seof: Host was unable to save file after transmission");
  372.  
  373. /*--------------------------------------------------------------------*/
  374. /*                   If local spool file, delete it                   */
  375. /*--------------------------------------------------------------------*/
  376.  
  377.  
  378.    if (purge_file && !equal(dName,"D.0"))
  379.    {
  380.      char hostName[FILENAME_MAX];
  381.      importpath(hostName, dName, rmtname);
  382.      unlink( hostName );
  383.      printmsg(4,"seof: Deleted file %s (%s)", dName, hostName );
  384.    } /* if (purge_file && !equal(dName,"D.0")) */
  385.  
  386. /*--------------------------------------------------------------------*/
  387. /*                            Update stats                            */
  388. /*--------------------------------------------------------------------*/
  389.  
  390.    remote_stats.fsent++;
  391.    remote_stats.bsent += bytes;
  392.  
  393.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  394.    {
  395.       ftime(&now);
  396.       ticks = (now.time - startTime.time) * 1000 +
  397.                ((long) now.millitm - (long) startTime.millitm);
  398.       printmsg(2, "Transfer completed, %ld chars/sec",
  399.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  400.  
  401.       if (bflag[F_SYSLOG])
  402.       {
  403.          tmx = localtime(&now.time);
  404.          if ( bflag[F_MULTITASK] )
  405.             syslog = FOPEN(SYSLOG, "a",TEXT_MODE);
  406.  
  407.          if ( syslog == NULL )
  408.             printerr(SYSLOG);
  409. #ifndef _Windows
  410.          else if ((bflag[F_MULTITASK] && setvbuf( syslog, NULL, _IONBF, 0)))
  411.             printerr(SYSLOG);
  412. #endif
  413.          else {
  414.             fprintf( syslog,
  415.                    "%s!%s %c %s (%d/%d-%02d:%02d:%02d) -> %ld"
  416.                            " / %ld.%02d secs\n",
  417.                    hostp->via,
  418.                    userid,
  419.                    type,
  420.                    lName,
  421.                    (tmx->tm_mon+1), tmx->tm_mday,
  422.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec, bytes,
  423.                    ticks / 1000 , (int) ((ticks % 1000) / 10) );
  424.             if ( bflag[F_MULTITASK] )
  425.             {
  426.                fclose( syslog );
  427.                syslog = NULL;
  428.             }
  429.          }
  430.  
  431.       } /* if (bflag[F_SYSLOG]) */
  432.  
  433.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  434.  
  435. /*--------------------------------------------------------------------*/
  436. /*                      Return success to caller                      */
  437. /*--------------------------------------------------------------------*/
  438.  
  439.    return XFER_FILEDONE;    /* go get the next file to process */
  440.  
  441. } /*seof*/
  442.  
  443. /*--------------------------------------------------------------------*/
  444. /*    n e w r e q u e s t                                             */
  445. /*                                                                    */
  446. /*    Determine the next request to be sent to other host             */
  447. /*--------------------------------------------------------------------*/
  448.  
  449. XFER_STATE newrequest( void )
  450. {
  451.    int i;
  452.  
  453. /*--------------------------------------------------------------------*/
  454. /*                 Verify we have no work in progress                 */
  455. /*--------------------------------------------------------------------*/
  456.  
  457.    if (!(xfer_stream == NULL))
  458.       return XFER_ABORT;      /* Something is already being
  459.                                  transferred; we're in trouble!      */
  460.  
  461. /*--------------------------------------------------------------------*/
  462. /*    Look for work in the current call file; if we do not find       */
  463. /*    any, the job is complete and we can delete all the files we     */
  464. /*    worked on in the file                                           */
  465. /*--------------------------------------------------------------------*/
  466.  
  467.    if (fgets(databuf, xferBufSize, fwork) == nil(char)) /* More data?     */
  468.    {                          /* No --> clean up list of files       */
  469.       printmsg(3, "newrequest: EOF for workfile %s",workfile);
  470.       fclose(fwork);
  471.       fwork = nil(FILE);
  472.       unlink(workfile);       /* Delete completed call file          */
  473.       return XFER_NEXTJOB;    /* Get next C.* file to process     */
  474.    } /* if (fgets(databuf, xferBufSize, fwork) == nil(char)) */
  475.  
  476. /*--------------------------------------------------------------------*/
  477. /*                  We have a new request to process                  */
  478. /*--------------------------------------------------------------------*/
  479.  
  480.    i = strlen(databuf) - 1;
  481.    printmsg(3, "newrequest: got command from %s",workfile);
  482.    if (databuf[i] == '\n')            /* remove new_line from card */
  483.       databuf[i] = '\0';
  484.  
  485.    *cmdopts = *dName = '\0';
  486.  
  487.    sscanf(databuf, "%c %s %s %s %s %s",
  488.          &type, fName, tName, spolName, cmdopts, dName);
  489.  
  490.    if ( !strlen( dName ))
  491.       strcpy( dName, "D.0");
  492.  
  493.    spolName[ sizeof userid - 1] = '\0';
  494.    strcpy( userid, spolName );
  495.  
  496. /*--------------------------------------------------------------------*/
  497. /*                           Reset counters                           */
  498. /*--------------------------------------------------------------------*/
  499.  
  500.    bytes = 0;
  501.    ftime(&startTime);
  502.    (*filepkt)();              /* Init for file transfer */
  503.  
  504. /*--------------------------------------------------------------------*/
  505. /*             Process the command according to its type              */
  506. /*--------------------------------------------------------------------*/
  507.  
  508.    switch( type )
  509.    {
  510.       case 'R':
  511.          return XFER_GETFILE;
  512.  
  513.       case 'S':
  514.          return XFER_PUTFILE;
  515.  
  516.       default:
  517.          return XFER_FILEDONE;   /* Ignore the line                  */
  518.    } /* switch */
  519.  
  520. } /* newrequest */
  521.  
  522. /*--------------------------------------------------------------------*/
  523. /*    s s f i l e                                                     */
  524. /*                                                                    */
  525. /*    Send File Header for file to be sent                            */
  526. /*--------------------------------------------------------------------*/
  527.  
  528. XFER_STATE ssfile( void )
  529. {
  530.    char hostFile[FILENAME_MAX];
  531.    char *fileName;
  532.  
  533. /*--------------------------------------------------------------------*/
  534. /*              Convert the file name to our local name               */
  535. /*--------------------------------------------------------------------*/
  536.  
  537.    if (equal(dName, "D.0"))   /* Is there a spool file?              */
  538.    {
  539.       fileName = fName;       /* No --> Use the real name            */
  540.       strcpy( hostFile, fileName );
  541.    }
  542.    else {
  543.       fileName = dName;       /* Yes --> Use it                      */
  544.       importpath(hostFile, fileName, rmtname);  /* And map to local  */
  545.    }
  546.  
  547.    lName = fName;             // Always log the real name
  548.  
  549. /*--------------------------------------------------------------------*/
  550. /*    Try to open the file; if we fail, we just continue, because we  */
  551. /*    may have sent the file on a previous call which failed part     */
  552. /*    way through this job                                            */
  553. /*--------------------------------------------------------------------*/
  554.  
  555.    xfer_stream = FOPEN( hostFile, "r", BINARY_MODE);
  556.                                     /* Open stream to send           */
  557.    if (xfer_stream == NULL)
  558.    {
  559.       printmsg(0, "ssfile: Cannot open file %s (%s).", fileName, hostFile);
  560.       printerr(hostFile);
  561.       return XFER_FILEDONE;      /* Try next file in this job  */
  562.    } /* if */
  563.  
  564. /*--------------------------------------------------------------------*/
  565. /*              The file is open, now set its buffering               */
  566. /*--------------------------------------------------------------------*/
  567.  
  568. #ifndef _Windows                 // Leave file buffered under Windows
  569.  
  570.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  571.    {
  572.       printmsg(0, "ssfile: Cannot unbuffer file %s (%s).",
  573.                   fileName, hostFile);
  574.       printerr(hostFile);
  575.       fclose(xfer_stream);
  576.       xfer_stream = NULL;
  577.       return XFER_ABORT;         /* Clearly not our day; quit  */
  578.    } /* if */
  579.  
  580. #endif
  581.  
  582. /*--------------------------------------------------------------------*/
  583. /*    Okay, we have a file to process; offer it to the other host     */
  584. /*--------------------------------------------------------------------*/
  585.  
  586.    printmsg( equal(fName,dName) ? 2 : 0,
  587.             "Sending \"%s\" (%s) as \"%s\"", fName, hostFile, tName);
  588.    if (!pktsendstr( databuf ))   /* Tell them what is coming at them */
  589.    {
  590.       fclose(xfer_stream);
  591.       xfer_stream = NULL;
  592.       return XFER_LOST;
  593.    }
  594.  
  595.    if (!pktgetstr((char *)databuf))
  596.    {
  597.       fclose(xfer_stream);
  598.       xfer_stream = NULL;
  599.       return XFER_LOST;
  600.    }
  601.  
  602.    if ((*databuf != 'S') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  603.    {
  604.       printmsg(0,"Invalid response from remote: %s",databuf);
  605.       fclose(xfer_stream);
  606.       xfer_stream = NULL;
  607.       return XFER_ABORT;
  608.    }
  609.  
  610.    if (databuf[1] != 'Y')     /* Otherwise reject file transfer?     */
  611.    {                          /* Yes --> Look for next file          */
  612.       printmsg(0, "ssfile: Remote host rejected file %s, reason %s",
  613.                    tName,
  614.                    databuf[2] ? (char *) &databuf[2] : "unknown" );
  615.       fclose( xfer_stream );
  616.       xfer_stream = NULL;
  617.       return XFER_FILEDONE;
  618.    }
  619.  
  620.    return XFER_SENDDATA;      /* Enter data transmission mode        */
  621.  
  622. } /*ssfile*/
  623.  
  624. /*--------------------------------------------------------------------*/
  625. /*    s r f i l e                                                     */
  626. /*                                                                    */
  627. /*    Send File Header for file to be received                        */
  628. /*--------------------------------------------------------------------*/
  629.  
  630. XFER_STATE srfile( void )
  631. {
  632.    struct  stat    statbuf;
  633.  
  634. /*--------------------------------------------------------------------*/
  635. /*               Convert the filename to our local name               */
  636. /*--------------------------------------------------------------------*/
  637.  
  638.    strcpy( spolName, normalize(tName));
  639.                                     // Assume the local user can type
  640.  
  641. /*--------------------------------------------------------------------*/
  642. /*    If the destination is a directory, put the originating          */
  643. /*    original file name at the end of the path                       */
  644. /*--------------------------------------------------------------------*/
  645.  
  646.    if ((spolName[strlen(spolName) - 1] == '/') ||
  647.        ((stat(spolName , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  648.    {
  649.       char *slash = strrchr( fName, '/');
  650.  
  651.       if ( slash == NULL )
  652.          slash = fName;
  653.       else
  654.          slash ++ ;
  655.  
  656.       printmsg(3, "srfile: Destination \"%s\" is directory, \
  657. appending file name \"%s\"", spolName, slash);
  658.  
  659.       if (spolName[strlen(spolName) - 1] != '/')
  660.          strcat(spolName, "/");
  661.  
  662.       strcat( spolName, slash );
  663.    } /* if */
  664.  
  665.    printmsg(0, "Receiving \"%s\" as \"%s\" (%s)", fName, tName, spolName);
  666.  
  667.    if (!pktsendstr( databuf ))
  668.       return XFER_LOST;
  669.  
  670.    if (!pktgetstr((char *)databuf))
  671.       return XFER_LOST;
  672.  
  673.    if ((*databuf != 'R') || ((databuf[1] != 'N') && (databuf[1] != 'Y')))
  674.    {
  675.       printmsg(0,"Invalid response from remote: %s",
  676.                   databuf);
  677.       return XFER_ABORT;
  678.    }
  679.  
  680.    if (databuf[1] != 'Y')     /* Otherwise reject file transfer?     */
  681.    {                          /* Yes --> Look for next file          */
  682.       printmsg(0, "srfile: Remote host denied access to file %s, reason %s",
  683.          fName, databuf[2] ? (char *) &databuf[2] : "unknown" );
  684.       return XFER_FILEDONE;
  685.    }
  686.  
  687. /*--------------------------------------------------------------------*/
  688. /*    We should verify the directory exists if the user doesn't       */
  689. /*    specify the -d option, but I've got enough problems this        */
  690. /*    week; we'll just auto-create using FOPEN()                      */
  691. /*--------------------------------------------------------------------*/
  692.  
  693.    xfer_stream = FOPEN(spolName, "w", BINARY_MODE);
  694.                            /* Allow auto-create of directory      */
  695.    if (xfer_stream == NULL)
  696.    {
  697.       printmsg(0, "srfile: cannot create %s", spolName);
  698.       printerr(spolName);
  699.       return XFER_ABORT;
  700.    }
  701.  
  702. /*--------------------------------------------------------------------*/
  703. /*                     Set buffering for the file                     */
  704. /*--------------------------------------------------------------------*/
  705.  
  706.  
  707. #ifndef _Windows                 // Leave file buffered under Windows
  708.  
  709.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  710.    {
  711.       printmsg(0, "srfile: Cannot unbuffer file %s (%s).",
  712.           tName, spolName);
  713.       printerr(spolName);
  714.       unlink(spolName);
  715.       fclose(xfer_stream);
  716.       xfer_stream = NULL;
  717.       return XFER_ABORT;
  718.    } /* if */
  719.  
  720. #endif
  721.  
  722.    spool = FALSE;             /* Do not rename file at completion */
  723.    lName = spolName;          // Use full name for local logging
  724.    return XFER_RECVDATA;      /* Now start receiving the data     */
  725.  
  726. } /*srfile*/
  727.  
  728. /*--------------------------------------------------------------------*/
  729. /*    s i n i t                                                       */
  730. /*                                                                    */
  731. /*    Send Initiate:  send this host's parameters and get other       */
  732. /*    side's back.                                                    */
  733. /*--------------------------------------------------------------------*/
  734.  
  735. XFER_STATE sinit( void )
  736. {
  737.    if ((*openpk)( TRUE ))     /* Initialize in caller mode           */
  738.       return XFER_ABORT;
  739.    else {
  740.       buf_init();
  741.       return XFER_MASTER;
  742.    } /* else */
  743.  
  744. } /*sinit*/
  745.  
  746.  
  747. /*********************** MISC SUB SUB PROTOCOL *************************/
  748.  
  749. /*
  750.    s c h k d i r
  751.  
  752.    scan spooling directory for C.* files for the other system
  753. */
  754.  
  755. XFER_STATE schkdir( const boolean outbound, const char callgrade )
  756. {
  757.    XFER_STATE c;
  758.  
  759.    if ( hostp->hsecure->sendfiles || outbound )
  760.                                  /* Send our work to other host?        */
  761.    {
  762.       c = scandir(rmtname,callgrade);
  763.                                  /* Determine if data for the host      */
  764.       scandir( NULL,callgrade ); /* Reset directory search pointers     */
  765.    }
  766.    else {
  767.       hostp->hstatus = called;/* Update host status flags            */
  768.       c = XFER_NOLOCAL;       /* Do not send data on inbound call    */
  769.    }
  770.  
  771.    switch ( c )
  772.    {
  773.       case XFER_ABORT:        /* Internal error opening file         */
  774.          return XFER_ABORT;
  775.  
  776.       case XFER_NOLOCAL:      /* No work for host                    */
  777.          if (! pktsendstr("HY") )
  778.             return XFER_LOST;
  779.  
  780.          if (!pktgetstr((char *)databuf))
  781.             return XFER_LOST; /* Didn't get response, die quietly    */
  782.          else {
  783.             hostp->hstatus = called;/* Update host status flags            */
  784.             return XFER_ENDP; /* Got response, we're out of here     */
  785.          }
  786.  
  787.       case XFER_REQUEST:
  788.          if (! pktsendstr("HN") )
  789.             return XFER_LOST;
  790.          else {
  791.             printmsg( 2, "schkdir: Switch into master mode" );
  792.             return XFER_MASTER;
  793.          }
  794.  
  795.       default:
  796.          panic();
  797.          return XFER_ABORT;
  798.  
  799.    } /* switch */
  800. } /*schkdir*/
  801.  
  802. /*--------------------------------------------------------------------*/
  803. /*    e n d p                                                         */
  804. /*                                                                    */
  805. /*    end the protocol                                                */
  806. /*--------------------------------------------------------------------*/
  807.  
  808. XFER_STATE endp( void )
  809. {
  810.    (*closepk)();
  811.  
  812.    if (spool)
  813.    {
  814.       unlink(tempName);
  815.       spool = FALSE;
  816.    }
  817.    return XFER_EXIT;
  818.  
  819. } /*endp*/
  820.  
  821.  
  822. /*********************** RECIEVE PROTOCOL **********************/
  823.  
  824. /*--------------------------------------------------------------------*/
  825. /*    r i n i t                                                       */
  826. /*                                                                    */
  827. /*    Receive Initialization                                          */
  828. /*--------------------------------------------------------------------*/
  829.  
  830. XFER_STATE rinit( void )
  831. {
  832.  
  833.    if ((*openpk)( FALSE ) == DCP_OK )   /* Initialize in callee mode */
  834.    {
  835.       buf_init();
  836.       return XFER_SLAVE;
  837.    }
  838.    else
  839.       return XFER_LOST;
  840.  
  841. } /*rinit*/
  842.  
  843. /*--------------------------------------------------------------------*/
  844. /*    r h e a d e r                                                   */
  845. /*                                                                    */
  846. /*    Receive File Header                                             */
  847. /*--------------------------------------------------------------------*/
  848.  
  849. XFER_STATE rheader( void )
  850. {
  851.  
  852.    if (!pktgetstr(databuf))
  853.       return XFER_LOST;
  854.  
  855. /*--------------------------------------------------------------------*/
  856. /*        Return if the remote system has no more data for us         */
  857. /*--------------------------------------------------------------------*/
  858.  
  859.    if ((databuf[0] & 0x7f) == 'H')
  860.       return XFER_NOREMOTE;   /* Report master has no more data to   */
  861.  
  862. /*--------------------------------------------------------------------*/
  863. /*                  Begin transforming the file name                  */
  864. /*--------------------------------------------------------------------*/
  865.  
  866.    *cmdopts = *dName = '\0';
  867.  
  868.    sscanf(databuf, "%c %s %s %s %s %s",
  869.          &type, fName, tName, spolName, cmdopts, dName);
  870.  
  871.    if ( !strlen( dName ))
  872.       strcpy( dName, "D.0");
  873.  
  874.    spolName[ sizeof userid - 1] = '\0';
  875.    strcpy( userid, spolName );
  876.  
  877. /*--------------------------------------------------------------------*/
  878. /*                           Reset counters                           */
  879. /*--------------------------------------------------------------------*/
  880.  
  881.    ftime(&startTime);
  882.    bytes = 0;
  883.    (*filepkt)();              /* Init for file transfer */
  884.  
  885. /*--------------------------------------------------------------------*/
  886. /*                 Return with next state to process                  */
  887. /*--------------------------------------------------------------------*/
  888.  
  889.    switch (type)
  890.    {
  891.       case 'R':
  892.          return XFER_GIVEFILE;
  893.  
  894.       case 'S':
  895.          return XFER_TAKEFILE;
  896.  
  897.       default:
  898.          printmsg(0,"rheader: Unsupported verb \"%c\" rejected",type);
  899.          if (!pktsendstr("XN"))  /* Reject the request               */
  900.             return XFER_LOST;    /* Die if reponse fails             */
  901.          else
  902.             return XFER_FILEDONE;   /* Process next request          */
  903.    } /* switch */
  904.  
  905. } /* rheader */
  906.  
  907. /*--------------------------------------------------------------------*/
  908. /*    r r f i l e                                                     */
  909. /*                                                                    */
  910. /*    Setup for receiving a file as requested by the remote host      */
  911. /*--------------------------------------------------------------------*/
  912.  
  913. XFER_STATE rrfile( void )
  914. {
  915.    char fileName[FILENAME_MAX];
  916.    size_t subscript;
  917.    struct  stat    statbuf;
  918.  
  919. /*--------------------------------------------------------------------*/
  920. /*       Determine if the file can go into the spool directory        */
  921. /*--------------------------------------------------------------------*/
  922.  
  923.    if ( isupper(*tName) &&
  924.         (tName[1] == '.') &&
  925.         (strchr(tName,'/') == NULL ) &&
  926.         (strchr(tName,'\\') == NULL ))
  927.       spool = TRUE;
  928.    else
  929.       spool = FALSE;
  930.  
  931.    strcpy( fileName, tName );
  932.  
  933.    if ( ! spool )
  934.       expand_path( fileName, securep->pubdir, securep->pubdir , NULL );
  935.  
  936. /*--------------------------------------------------------------------*/
  937. /*       Check if the name is a directory name (end with a '/')       */
  938. /*--------------------------------------------------------------------*/
  939.  
  940.    subscript = strlen( fileName ) - 1;
  941.  
  942.    if ((fileName[subscript] == '/') ||
  943.        ((stat(fileName , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  944.    {
  945.       char *slash = strrchr(fName, '/');
  946.       if (slash  == NULL)
  947.          slash = fName;
  948.       else
  949.          slash++;
  950.  
  951.       printmsg(3, "rrfile: destination is directory \"%s\", adding \"%s\"",
  952.                fileName, slash);
  953.  
  954.       if ( fileName[ subscript ] != '/')
  955.          strcat(fileName, "/");
  956.       strcat(fileName, slash);
  957.    } /* if */
  958.  
  959. /*--------------------------------------------------------------------*/
  960. /*          Let host munge filename as appropriate                    */
  961. /*--------------------------------------------------------------------*/
  962.  
  963.    importpath(spolName, fileName, rmtname);
  964.  
  965. /*--------------------------------------------------------------------*/
  966. /*       If the name has a path and we don't allow it, reject the     */
  967. /*       transfer.  We also reject attempts to send call files,       */
  968. /*       because they would bypass security.                          */
  969. /*--------------------------------------------------------------------*/
  970.  
  971.    if (( !spool && !ValidateFile( spolName , ALLOW_WRITE )) ||
  972.        ( spool && (*tName == 'C' )))
  973.    {
  974.       if (!pktsendstr("SN2")) /* Report access denied to requestor   */
  975.          return XFER_LOST;
  976.       else
  977.          return XFER_FILEDONE;   /* Look for next file from master   */
  978.    } /* if */
  979.  
  980. /*--------------------------------------------------------------------*/
  981. /*            The filename is transformed, try to open it             */
  982. /*--------------------------------------------------------------------*/
  983.  
  984.    if (spool)
  985. #ifdef __TURBOC__
  986.    {
  987.       char *p = tmpnam( tempName );
  988.       denormalize( p );
  989.       xfer_stream = fopen( p, "wb");
  990.    }
  991. #else
  992.  
  993. /*--------------------------------------------------------------------*/
  994. /*    MS C 6.0 doesn't generate the name for the current directory,   */
  995. /*    so we cheat and use our own temporary file name generation      */
  996. /*    routine.                                                        */
  997. /*--------------------------------------------------------------------*/
  998.  
  999.    {
  1000.       char *savetemp = E_tempdir;   /* Save the real temp directory  */
  1001.  
  1002.       E_tempdir = E_spooldir;       /* Generate this file in spool   */
  1003.       mktempname(tempName, "TMP");  /* Get the file name             */
  1004.       E_tempdir = savetemp;         /* Restore true directory name   */
  1005.  
  1006.       denormalize( tempName );
  1007.       xfer_stream = fopen( tempName , "wb");
  1008.  
  1009.    }
  1010. #endif
  1011.  
  1012.    else if (strchr( cmdopts,'d'))
  1013.       xfer_stream = FOPEN( spolName, "w", BINARY_MODE);
  1014.    else {
  1015.       denormalize( spolName );
  1016.       xfer_stream = fopen( spolName, "wb");
  1017.    }
  1018.  
  1019.  
  1020.    if (xfer_stream == NULL)
  1021.    {
  1022.       printmsg(0, "rrfile: cannot open file %s (%s).",
  1023.            fileName, spool ? tempName : spolName);
  1024.       printerr(spool ? tempName : spolName);
  1025.       if (!pktsendstr("SN4"))    /* Report cannot create file     */
  1026.          return XFER_LOST;       /* School is out, die            */
  1027.       else
  1028.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1029.    } /* if */
  1030.  
  1031. /*--------------------------------------------------------------------*/
  1032. /*               The file is open, now try to buffer it               */
  1033. /*--------------------------------------------------------------------*/
  1034.  
  1035.  
  1036. #ifndef _Windows                 // Leave file buffered under Windows
  1037.  
  1038.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  1039.    {
  1040.       printmsg(0, "rrfile: Cannot unbuffer file %s (%s).",
  1041.           fileName, spool ? tempName : spolName);
  1042.       printerr(spool ? tempName : spolName);
  1043.       fclose(xfer_stream);
  1044.       xfer_stream = NULL;
  1045.       pktsendstr("SN4");             /* Report cannot create file     */
  1046.       return XFER_ABORT;
  1047.    } /* if */
  1048.  
  1049. #endif
  1050.  
  1051. /*--------------------------------------------------------------------*/
  1052. /*    Announce we are receiving the file to console and to remote     */
  1053. /*--------------------------------------------------------------------*/
  1054.  
  1055.    printmsg(spool ? 2 : 0 , "Receiving \"%s\" as \"%s\" (%s)",
  1056.                fName,fileName,spolName);
  1057.  
  1058.    if (spool)
  1059.       printmsg(2,"Using temp name %s",tempName);
  1060.  
  1061.    if (!pktsendstr("SY"))
  1062.    {
  1063.       fclose(xfer_stream);
  1064.       xfer_stream = NULL;
  1065.       return XFER_LOST;
  1066.    }
  1067.  
  1068.    lName = spool ? tName : spolName;   // choose name to log
  1069.  
  1070.    return XFER_RECVDATA;   /* Switch to data state                */
  1071.  
  1072. } /*rrfile*/
  1073.  
  1074. /*--------------------------------------------------------------------*/
  1075. /*    r s f i l e                                                     */
  1076. /*                                                                    */
  1077. /*    Receive File Header for a file remote has requested us to       */
  1078. /*    send                                                            */
  1079. /*--------------------------------------------------------------------*/
  1080.  
  1081. XFER_STATE rsfile( void )
  1082. {
  1083.    char fileName[FILENAME_MAX];
  1084.    struct  stat    statbuf;
  1085.    size_t subscript;
  1086.  
  1087.    expand_path( strcpy(fileName, fName ) ,
  1088.                 securep->pubdir ,
  1089.                 securep->pubdir ,
  1090.                 NULL );
  1091.  
  1092. /*--------------------------------------------------------------------*/
  1093. /*               Let host munge filename as appropriate               */
  1094. /*--------------------------------------------------------------------*/
  1095.  
  1096.    strcpy( spolName, fileName );    // Assume remote can type ...
  1097.                                     // don't munge the file they want
  1098.                                     // sent
  1099.  
  1100. /*--------------------------------------------------------------------*/
  1101. /*       Check if the name is a directory name (end with a '/')       */
  1102. /*--------------------------------------------------------------------*/
  1103.  
  1104.    subscript = strlen( fileName ) - 1;
  1105.  
  1106.    if ((fileName[subscript] == '/') ||
  1107.        ((stat(spolName , &statbuf) == 0) && (statbuf.st_mode & S_IFDIR)))
  1108.    {
  1109.       printmsg(3, "rsfile: source is directory \"%s\", rejecting",
  1110.                spolName);
  1111.  
  1112.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  1113.          return XFER_LOST;       /* School is out, die            */
  1114.       else
  1115.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1116.    } /* if */
  1117.  
  1118. /*--------------------------------------------------------------------*/
  1119. /*                Check the access to the file desired                */
  1120. /*--------------------------------------------------------------------*/
  1121.  
  1122.    if ( !ValidateFile( spolName , ALLOW_READ ))
  1123.    {
  1124.       if (!pktsendstr("RN2")) /* Report access denied to requestor   */
  1125.          return XFER_LOST;
  1126.       else
  1127.          return XFER_FILEDONE;   /* Look for next file from master   */
  1128.    } /* if */
  1129.  
  1130. /*--------------------------------------------------------------------*/
  1131. /*            The filename is transformed, try to open it             */
  1132. /*--------------------------------------------------------------------*/
  1133.  
  1134.    xfer_stream = FOPEN( spolName, "r" , BINARY_MODE);
  1135.                               /* Open stream to transmit       */
  1136.    if (xfer_stream == NULL)
  1137.    {
  1138.       printmsg(0, "rsfile: Cannot open file %s (%s).", fName, spolName);
  1139.       printerr(spolName);
  1140.       if (!pktsendstr("RN2"))    /* Report cannot send file       */
  1141.          return XFER_LOST;       /* School is out, die            */
  1142.       else
  1143.          return XFER_FILEDONE;   /* Tell them to send next file   */
  1144.    } /* if */
  1145.  
  1146.  
  1147. #ifndef _Windows                 // Leave file buffered under Windows
  1148.  
  1149.    if (setvbuf( xfer_stream, NULL, _IONBF, 0))
  1150.    {
  1151.       printmsg(0, "rsfile: Cannot unbuffer file %s (%s).", fName, spolName);
  1152.       pktsendstr("RN2");         /* Tell them we cannot handle it */
  1153.       printerr(spolName);
  1154.       fclose(xfer_stream);
  1155.       xfer_stream = NULL;
  1156.       return XFER_ABORT;
  1157.    } /* if */
  1158.  
  1159. #endif
  1160.  
  1161. /*--------------------------------------------------------------------*/
  1162. /*  We have the file open, announce it to the log and to the remote   */
  1163. /*--------------------------------------------------------------------*/
  1164.  
  1165.    if (!pktsendstr("RY"))
  1166.    {
  1167.       fclose(xfer_stream);
  1168.       xfer_stream = NULL;
  1169.       return XFER_LOST;
  1170.    }
  1171.  
  1172.    printmsg(0, "Sending \"%s\" (%s) as \"%s\"", fName, spolName, tName);
  1173.  
  1174.    lName = spolName;       // Remember name of file to log
  1175.  
  1176.    return XFER_SENDDATA;   /* Switch to send data state        */
  1177.  
  1178. } /*rsfile*/
  1179.  
  1180. /*--------------------------------------------------------------------*/
  1181. /*    r d a t a                                                       */
  1182. /*                                                                    */
  1183. /*    Receive Data                                                    */
  1184. /*--------------------------------------------------------------------*/
  1185.  
  1186. XFER_STATE rdata( void )
  1187. {
  1188.    short    len;
  1189.    int    used = 0;
  1190.  
  1191.    do {
  1192.  
  1193.       if ((*getpkt)((char *) (databuf + used), &len) != DCP_OK)
  1194.       {
  1195.          fclose(xfer_stream);
  1196.          xfer_stream = NULL;
  1197.          return XFER_LOST;
  1198.       }
  1199.       else
  1200.          used += len;
  1201.  
  1202.    }  while (((int) (used + r_pktsize) <= (int) xferBufSize) && len);
  1203.  
  1204. /*--------------------------------------------------------------------*/
  1205. /*                  Write incoming data to the file                   */
  1206. /*--------------------------------------------------------------------*/
  1207.  
  1208.    if (used && (bufwrite((char *) databuf, used) < (int) used))
  1209.    {                                                        /* ahd   */
  1210.       printmsg(0, "rdata: Error writing data to file.");
  1211.       fclose(xfer_stream);
  1212.       xfer_stream = NULL;
  1213.       return XFER_ABORT;
  1214.    }
  1215.  
  1216. /*--------------------------------------------------------------------*/
  1217. /*                         Handle end of file                         */
  1218. /*--------------------------------------------------------------------*/
  1219.  
  1220.    if (len == 0)
  1221.       return XFER_RECVEOF;
  1222.    else
  1223.       return XFER_RECVDATA;      /* Remain in data state                */
  1224.  
  1225. } /*rdata*/
  1226.  
  1227. /*--------------------------------------------------------------------*/
  1228. /*    r e o f                                                         */
  1229. /*                                                                    */
  1230. /*    Process EOF for a received file                                 */
  1231. /*--------------------------------------------------------------------*/
  1232.  
  1233. XFER_STATE reof( void )
  1234. {
  1235.    struct tm *tmx;
  1236.    struct timeb now;
  1237.    long ticks;
  1238.    char *cy = "CY";
  1239.    char *cn = "CN";
  1240.    char *response = cy;
  1241.    char *rName = spool ? tempName : spolName;
  1242.                               // Name to delete if we have a problem
  1243.  
  1244. /*--------------------------------------------------------------------*/
  1245. /*            Close out the file, checking for I/O errors             */
  1246. /*--------------------------------------------------------------------*/
  1247.  
  1248.    fclose(xfer_stream);
  1249.    if (ferror (xfer_stream ))
  1250.    {
  1251.       response = cn;          /* Report we had a problem             */
  1252.       printerr( rName );
  1253.    }
  1254.  
  1255.    xfer_stream = NULL;        /* To make sure!                       */
  1256.  
  1257. /*--------------------------------------------------------------------*/
  1258. /*    If it was a spool file, rename it to its permanent location     */
  1259. /*--------------------------------------------------------------------*/
  1260.  
  1261.    if (spool && equal(response,cy))
  1262.    {
  1263.       unlink( spolName );     /* Should be safe, since we only do it
  1264.                                  for spool files                     */
  1265.  
  1266.       if ( RENAME(tempName, spolName ))
  1267.       {
  1268.          printmsg(0,"reof: Unable to rename %s to %s",
  1269.                   tempName, spolName);
  1270.          response = cn;
  1271.          printerr(spolName);
  1272.       } /* if ( RENAME(tempName, spolName )) */
  1273.       spool = FALSE;
  1274.    } /* if (equal(response,cy) && spool) */
  1275.  
  1276.    if (!pktsendstr(response)) /* Announce we accepted the file       */
  1277.       return XFER_LOST;       /* No ACK?  Return, if so              */
  1278.  
  1279.    if ( !equal(response, cy) )   /* If we had an error, delete file  */
  1280.    {
  1281.       printmsg(0,"reof: Deleting corrupted file %s", rName );
  1282.       unlink(rName );
  1283.       return XFER_ABORT;
  1284.    } /* if ( !equal(response, cy) ) */
  1285.  
  1286. /*--------------------------------------------------------------------*/
  1287. /*            The file is delivered; compute stats for it             */
  1288. /*--------------------------------------------------------------------*/
  1289.  
  1290.    remote_stats.freceived++;
  1291.    remote_stats.breceived += bytes;
  1292.  
  1293.    if (bflag[F_SYSLOG] || (debuglevel > 2 ))
  1294.    {
  1295.       ftime(&now);
  1296.       ticks = (now.time - startTime.time) * 1000 +
  1297.                ((long) now.millitm - (long) startTime.millitm);
  1298.       printmsg(2, "Transfer completed, %ld chars/sec",
  1299.                   (long) ((bytes * 1000) / (ticks ? ticks : 1) ));
  1300.  
  1301.       if (bflag[F_SYSLOG])
  1302.       {
  1303.          tmx = localtime(&now.time);
  1304.          if ( bflag[F_MULTITASK] )
  1305.             syslog = FOPEN(SYSLOG, "a",TEXT_MODE);
  1306.  
  1307.          if ( syslog == NULL )
  1308.             printerr(SYSLOG);
  1309. #ifndef _Windows
  1310.          else if ((bflag[F_MULTITASK] && setvbuf( syslog, NULL, _IONBF, 0)))
  1311.             printerr(SYSLOG);
  1312. #endif
  1313.          else {
  1314.             fprintf( syslog,
  1315.                    "%s!%s %c %s (%d/%d-%02d:%02d:%02d) <- %ld"
  1316.                            " / %ld.%02d secs\n",
  1317.                    hostp->via,
  1318.                    userid,
  1319.                    type,
  1320.                    lName,
  1321.                    (tmx->tm_mon+1), tmx->tm_mday,
  1322.                    tmx->tm_hour, tmx->tm_min, tmx->tm_sec, bytes,
  1323.                    ticks / 1000 , (int) ((ticks % 1000) / 10) );
  1324.  
  1325.             if ( bflag[F_MULTITASK] )
  1326.             {
  1327.                fclose( syslog );
  1328.                syslog = NULL;
  1329.             }
  1330.          }
  1331.  
  1332.       } /* if (bflag[F_SYSLOG]) */
  1333.  
  1334.    } /* if (bflag[F_SYSLOG] || (debuglevel > 2 )) */
  1335.  
  1336. /*--------------------------------------------------------------------*/
  1337. /*                      Return success to caller                      */
  1338. /*--------------------------------------------------------------------*/
  1339.  
  1340.    return XFER_FILEDONE;    /* go get the next file to process */
  1341.  
  1342. } /* reof */
  1343.  
  1344. /*--------------------------------------------------------------------*/
  1345. /*                           MISC ROUTINES                            */
  1346. /*--------------------------------------------------------------------*/
  1347.  
  1348. /*--------------------------------------------------------------------*/
  1349. /*    p k t s e n d s t r                                             */
  1350. /*                                                                    */
  1351. /*    Transmit a control packet                                       */
  1352. /*--------------------------------------------------------------------*/
  1353.  
  1354. static boolean pktsendstr( char *s )
  1355. {
  1356.  
  1357.    printmsg(2, ">>> %s", s);
  1358.  
  1359. /*--------------------------------------------------------------------*/
  1360. /*    We flush here because we know we're in control and not          */
  1361. /*    waiting for remote data we could miss.                          */
  1362. /*--------------------------------------------------------------------*/
  1363.  
  1364.    if ( (! bflag[ F_MULTITASK ]) || (debuglevel > 2) )
  1365.       fflush( logfile );         /* Known safe place  to flush log      */
  1366.  
  1367.    if((*wrmsg)(s) != DCP_OK )
  1368.       return FALSE;
  1369.  
  1370.    remote_stats.bsent += strlen(s)+1;
  1371.  
  1372.    return TRUE;
  1373.  
  1374. } /* pktsendstr */
  1375.  
  1376. /*--------------------------------------------------------------------*/
  1377. /*    p k t g e t s t r                                               */
  1378. /*                                                                    */
  1379. /*    Receive a control packet                                        */
  1380. /*--------------------------------------------------------------------*/
  1381.  
  1382. static boolean pktgetstr( char *s)
  1383. {
  1384.    if ((*rdmsg)(s) != DCP_OK )
  1385.      return FALSE;
  1386.  
  1387.    remote_stats.breceived += strlen( s ) + 1;
  1388.    printmsg(2, "<<< %s", s);
  1389.  
  1390.    return TRUE;
  1391. } /* pktgetstr */
  1392.  
  1393. /*--------------------------------------------------------------------*/
  1394. /*    b u f _ i n i t                                                 */
  1395. /*                                                                    */
  1396. /*    Alocate buffers for file transfer                               */
  1397. /*--------------------------------------------------------------------*/
  1398.  
  1399. static void buf_init( void )
  1400. {
  1401.    xferBufSize = max( s_pktsize, r_pktsize ) * 4;
  1402.    if ( xferBufSize < BUFSIZ )
  1403.       xferBufSize = BUFSIZ;
  1404.    if ( xferBufSize < M_xfer_bufsize )
  1405.       xferBufSize = M_xfer_bufsize;
  1406.  
  1407. #if defined(__OS2__) || defined(WIN32)
  1408.    if ( xferBufSize < (16 * 1024) )
  1409.       xferBufSize = 16 * 1024;
  1410. #endif
  1411.  
  1412.    if (databuf == NULL)
  1413.       databuf = malloc( xferBufSize );
  1414.    else
  1415.       databuf = realloc( databuf, xferBufSize );
  1416.  
  1417.    checkref( databuf );
  1418.  
  1419. } /* buf_init */
  1420.